<?php

namespace App\Jobs;

use App\Models\NsSupplierGoodsCoupon;
use App\Models\XnH5Order;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Http;

class RechargeApi implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $tries = 3;       // 最大重试次数
    public $backoff = 30;    // 重试间隔(秒)

    /**
     * 创建新任务实例
     */
    public function __construct(public $data, public $url = '')
    {
        $this->url = $url ?: env('BATCH_RECHARGE_COUPON_URL', '');
    }

    /**
     * 执行任务
     */
    public function handle(): void
    {
        try {
            // 1. 更新订单状态
            $this->updateOrderStatus();

            // 2. 发送API请求
            $response = $this->sendRequest();

            // 3. 处理API响应
            $this->processResponse($response);

        } catch (\Throwable $e) {
            $this->logError($e);
            throw $e; // 触发队列重试
        }
    }

    /**
     * 更新订单支付状态
     */
    protected function updateOrderStatus(): void
    {
        XnH5Order::where('order_sn', $this->data['order_no'])
            ->update([
                'alipay_order' => $this->data['alipay_order'],
                'is_pay' => 1
            ]);
    }

    /**
     * 发送API请求
     */
    protected function sendRequest(): array
    {
        $payload = $this->buildRequestPayload();

        // 记录脱敏日志
        Log::channel('job')->info('请求接口', [
            'url' => $this->url,
            'payload' => $payload
        ]);

        $response = Http::asJson()
            ->timeout(15) // 15秒超时
            ->post($this->url, $payload);

        return $response->json() ?? [];
    }

    /**
     * 构建请求数据
     */
    protected function buildRequestPayload(): array
    {
        $payload = [
            'order_sn'        => $this->data['order_no'],
            'goods_id'        => $this->data['gid'],
            'account'         => $this->data['account'],
            'marchant_number' => $this->data['merchant'],
        ];

        if (!empty($this->data['coupon'])) {
            $payload['coupon'] = $this->data['coupon'];
        }

        ksort($payload);
        $payload['sign'] = $this->generateSignature($payload);

        return $payload;
    }

    /**
     * 生成签名
     */
    protected function generateSignature(array $payload): string
    {
        return md5(json_encode($payload, JSON_UNESCAPED_UNICODE) . $this->data['secret']);
    }

    /**
     * 处理API响应
     */
    protected function processResponse(array $response): void
    {
        Log::channel('job')->info('接口响应', [
            'code' => $response['code'] ?? null,
            'message' => $response['message'] ?? '无响应信息'
        ]);

        // 成功响应处理
        if (($response['code'] ?? 0) === 1000) {
            $this->markCouponUsed();
            return;
        }

        // 失败响应处理
        $this->logFailedOrder($response['message'] ?? '接口调用失败');
    }

    /**
     * 标记优惠券已使用
     */
    protected function markCouponUsed(): void
    {
        if (empty($this->data['coupon'])) return;

        NsSupplierGoodsCoupon::where('coupon', $this->data['coupon'])
            ->where('state', 2) // 只处理状态为2的优惠券
            ->update([
                'use_time' => Carbon::now(),
                'state' => 3,
                'order_sn' => $this->data['order_no']
            ]);
    }

    /**
     * 记录订单失败信息
     */
    protected function logFailedOrder(string $message): void
    {
        XnH5Order::where('order_sn', $this->data['order_no'])
            ->update(['message' => $message]);
    }

    /**
     * 记录错误日志（脱敏处理）
     */
    protected function logError(\Throwable $e): void
    {
        Log::channel('job')->error('订单处理失败: ' . $e->getMessage(), [
            'exception' => get_class($e),
            'order_no' => $this->data['order_no'] ?? null,
            'gid' => $this->data['gid'] ?? null,
            // 敏感信息脱敏
            'account' => isset($this->data['account'])
                ?? null,
            'coupon' => isset($this->data['coupon'])
                ??  null
        ]);
    }

    /**
     * 任务最终失败处理
     */
    public function failed(\Throwable $e): void
    {
        Log::channel('job')->critical('任务最终失败', [
            'order_no' => $this->data['order_no'] ?? 'unknown',
            'error' => $e->getMessage(),
            'trace' => $e->getTraceAsString()
        ]);
    }
}
